#include "syscalls.h"
#include <errno.h>
#include <signal.h>
#include "unistd.h"

#define SIGBAD(signo) (((signo) <= 0) || ((signo) > NSIG))

int sigemptyset(sigset_t * set)
{
	return (*set = 0);
}

int sigfillset(sigset_t * set)
{
	*set = ~((sigset_t)0);
	return 0;
}

int sigaddset(sigset_t * set, int signo)
{
	if(SIGBAD(signo)){
		errno = EINVAL;
		return -1;
	}

	*set |= 1 << (signo - 1);
	return 0;
}

int sigdelset(sigset_t * set, int signo)
{
	if(SIGBAD(signo)){
		errno = EINVAL;
		return -1;
	}

	*set &= ~(1 << (signo - 1));
	return 0;
}

int sigismember(const sigset_t * set, int signo)
{
	if(SIGBAD(signo)){
		errno = EINVAL;
		return -1;
	}

	return ((*set & (1 << (signo - 1))) != 0);
}

int sigprocmask(int how, const sigset_t * set, sigset_t * oset)
{
	int ret = 0;

	__asm__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_sigprocmask), "b"(how), "c"(set), "d"(oset)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int sigpending(sigset_t * set)
{
	int ret = 0;

	__asm__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_sigpending), "b"(set)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int sigaction(int signo, const struct sigaction * act, struct sigaction * oact)
{
	int ret = 0;
	struct kernel_sigaction kact, koact, * oa;
	struct kernel_sigaction *pkact = NULL;

	if (act)
	{
		kact.ksa_sigaction = act->sa_sigaction;
		kact.ksa_mask = act->sa_mask;
		kact.ksa_flags = act->sa_flags;

		pkact = &kact;
	}

	oa = NULL;
	if(oact)
		oa = &koact;

	__asm__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_sigaction), "b"(signo), "c"(pkact), "d"(oa)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	if(oact){
		oact->sa_sigaction = koact.ksa_sigaction;
		oact->sa_mask = koact.ksa_mask;
		oact->sa_flags = koact.ksa_flags;
	}

	return ret;
}

int sigsuspend(const sigset_t * sigmask)
{
	int ret = 0;

	__asm__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_sigsuspend), "b"(sigmask)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int sigpause(int sigmask)
{
	return sigsuspend((sigset_t)&sigmask);
}

int killpg(pid_t pid, int sig)
{
	pid_t pgrp;

	if (pid == 0)
	{
		pgrp = getpgrp(getpid());
	}
	else
	{
		pgrp = pid;
	}

	return kill(-pgrp, sig);
}

#ifndef HAVE_GNU_LD
#define _sys_siglist    sys_siglist
#endif


const char *const sys_siglist[] = 
{
	"Signal 0",
	"Hangup",
	"Interrupt",
	"Quit",
	"Illegal instruction",
	"Trace/BPT trap",
	"IOT trap",
	"EMT trap",
	"Floating point exception",
	"Killed",
	"Bus error",
	"Segmentation fault",
	"Bad system call",
	"Broken pipe",
	"Alarm clock",
	"Terminated",
	"Urgent I/O condition",
	"Stopped (signal)",
	"Stopped",
	"Continued",
	"Child exited",
	"Stopped (tty input)",
	"Stopped (tty output)",
	"I/O possible",
	"Cputime limit exceeded",
	"Filesize limit exceeded",
	"Virtual timer expired",
	"Profiling timer expired",
	"Window changed",
	"Resource lost",
	"User defined signal 1",
	"User defined signal 2",
	NULL
};

#if 0
#include "setjmp.h"

int sigsetjmp(sigjmp_buf env, int savemask)
{
	return setjmp(env);
}

int siglongjmp(sigjmp_buf env, int val)
{
	return longjmp(env, val);
}
#endif
